package com.lihua.project.system.user.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.PageHelper;
import com.lihua.common.constant.ShiroConstants;
import com.lihua.common.utils.*;
import com.lihua.common.utils.text.Convert;
import com.lihua.framework.config.RuoYiConfig;
import com.lihua.framework.shiro.service.PasswordService;
import com.lihua.framework.web.controller.BaseController;
import com.lihua.framework.web.domain.AjaxResult;
import com.lihua.framework.web.page.TableDataInfo;
import com.lihua.project.provider.ShowApiProvider;
import com.lihua.project.system.article.domain.Article;
import com.lihua.project.system.article.service.IArticleService;
import com.lihua.project.system.config.service.IConfigService;
import com.lihua.project.system.menu.domain.Menu;
import com.lihua.project.system.menu.service.IMenuService;
import com.lihua.project.system.notice.domain.Notice;
import com.lihua.project.system.notice.service.INoticeService;
import com.lihua.project.system.user.domain.PublicUser;
import com.lihua.project.system.user.domain.User;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 首页 业务处理
 *
 * @author ruoyi
 */
@Controller
public class IndexController extends BaseController {
    @Autowired
    private IMenuService menuService;

    @Autowired
    private IConfigService configService;

    @Autowired
    private PasswordService passwordService;

    @Autowired
    private RuoYiConfig ruoYiConfig;

    @Autowired
    private IArticleService articleService;

    @Autowired
    private ShowApiProvider showApiProvider;

    @Autowired
    private INoticeService noticeService;

    @Autowired
    private SystemCountUtils systemCountUtils;

    @Autowired
    private RedisUtils redisUtils;

    private String prefix = "index";


    // 前台首页
    @GetMapping("/index")
    public String index(Model model) {
        // 取身份信息
        User user = getSysUser();
        PublicUser publicUser =null;
        if (user!=null){
            publicUser = user.getPublicUser(user);
        }
        model.addAttribute("selfUser",publicUser);

        //励志名言获取
        JSONArray sayings = showApiProvider.getSaying(1);
        if (sayings!=null){
            model.addAttribute("saying", sayings.get(0));
        }



        //获取一张图片 ,方式一，随机风险大
        //String[] types = new String[]{"风景","动漫","汽车","萌宠","清新"};
        //Random random = new Random();
        //int i = random.nextInt(5);
        //String pictureUrl = showApiProvider.getPicture(types[i]);
        //方式二，必应图片，都是一些风景，风险小
        String pictureUrl = "https://qqlykm.cn/api/bing/get?type=rand";
        model.addAttribute("pictureUrl", pictureUrl);

        //获取公告
        //设置分页参数
        Notice notice = new Notice();
        PageHelper.startPage(1, 3, "create_time desc").setReasonable(true);
        List<Notice> noticeList = noticeService.selectNoticeList(notice);
        model.addAttribute("noticeList", noticeList);

        //新闻资讯
        //https://qqlykm.cn/api/wy/apijx.php?id=BD29LPUBwangning
        return prefix + "/index";
    }


    // 后台管理系统首页
    @GetMapping("/admin/index")
    @RequiresRoles("admin")
    public String adminIndex(ModelMap mmap) {
        // 取身份信息
        User user = getSysUser();
        // 根据用户id取出菜单
        List<Menu> menus = menuService.selectMenusByUser(user);
        mmap.put("menus", menus);
        mmap.put("user", user);
        mmap.put("sideTheme", configService.selectConfigByKey("sys.index.sideTheme"));
        mmap.put("skinName", configService.selectConfigByKey("sys.index.skinName"));
        Boolean footer = Convert.toBool(configService.selectConfigByKey("sys.index.footer"), true);
        Boolean tagsView = Convert.toBool(configService.selectConfigByKey("sys.index.tagsView"), true);
        mmap.put("footer", footer);
        mmap.put("tagsView", tagsView);
        mmap.put("mainClass", contentMainClass(footer, tagsView));
        mmap.put("copyrightYear", ruoYiConfig.getCopyrightYear());
        mmap.put("demoEnabled", ruoYiConfig.isDemoEnabled());
        mmap.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
        mmap.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
        mmap.put("isMobile", ServletUtils.checkAgentIsMobile(ServletUtils.getRequest().getHeader("User-Agent")));

        // 菜单导航显示风格
        String menuStyle = configService.selectConfigByKey("sys.index.menuStyle");
        // 移动端，默认使左侧导航菜单，否则取默认配置
        String indexStyle = ServletUtils.checkAgentIsMobile(ServletUtils.getRequest().getHeader("User-Agent")) ? "index" : menuStyle;

        // 优先Cookie配置导航菜单
        Cookie[] cookies = ServletUtils.getRequest().getCookies();
        for (Cookie cookie : cookies) {
            if (StringUtils.isNotEmpty(cookie.getName()) && "nav-style".equalsIgnoreCase(cookie.getName())) {
                indexStyle = cookie.getValue();
                break;
            }
        }
        String webIndex = "topnav".equalsIgnoreCase(indexStyle) ? "index-topnav" : "index";
        return webIndex;
    }


    // 锁定屏幕
    @GetMapping("/lockscreen")
    public String lockscreen(ModelMap mmap) {
        mmap.put("user", getSysUser());
        ServletUtils.getSession().setAttribute(ShiroConstants.LOCK_SCREEN, true);
        return "lock";
    }

    // 解锁屏幕
    @PostMapping("/unlockscreen")
    @ResponseBody
    public AjaxResult unlockscreen(String password) {
        User user = getSysUser();
        if (StringUtils.isNull(user)) {
            return AjaxResult.error("服务器超时，请重新登录");
        }
        if (passwordService.matches(user, password)) {
            ServletUtils.getSession().removeAttribute(ShiroConstants.LOCK_SCREEN);
            return AjaxResult.success();
        }
        return AjaxResult.error("密码不正确，请重新输入。");
    }

    // 切换主题
    @GetMapping("/system/switchSkin")
    public String switchSkin() {
        return "skin";
    }

    // 切换菜单
    @GetMapping("/system/menuStyle/{style}")
    public void menuStyle(@PathVariable String style, HttpServletResponse response) {
        CookieUtils.setCookie(response, "nav-style", style);
    }

    // 后台系统主页
    @GetMapping("/system/main")
    public String main(ModelMap mmap) {
        String userType = "user-count";
        String taskType = "task-count";
        String articleType = "article-count";
        mmap.put("version", ruoYiConfig.getVersion());

        //获取用户总数，今日新增，比昨天新增比例
        int userTotal = systemCountUtils.getTotal(userType);
        mmap.put("userTotal",String.format("%,d", userTotal));
        int userTodayNum = systemCountUtils.getTodayNum(userType);
        mmap.put("userTodayNum",String.format("%,d", userTodayNum));
        String userCompareYesterday = systemCountUtils.getCompareYesterday(userType);
        mmap.put("userCompare",userCompareYesterday);


        //获取任务计数
        int taskTotal = systemCountUtils.getTotal(taskType);
        mmap.put("taskTotal",String.format("%,d", taskTotal));
        int taskTodayNum = systemCountUtils.getTodayNum(taskType);
        mmap.put("taskTodayNum",String.format("%,d", taskTodayNum));
        String taskCompareYesterday = systemCountUtils.getCompareYesterday(taskType);
        mmap.put("taskCompare",taskCompareYesterday);


        //获取帖子计数
        int articleTotal = systemCountUtils.getTotal(articleType);
        mmap.put("articleTotal",String.format("%,d", articleTotal));
        int articleTodayNum = systemCountUtils.getTodayNum(articleType);
        mmap.put("articleTodayNum",String.format("%,d", articleTodayNum));
        String articleCompareYesterday = systemCountUtils.getCompareYesterday(articleType);
        mmap.put("articleCompare",articleCompareYesterday);

        return "main_v1";
    }

    /**
     *
     * 用户 type=user-count 新增：key = user-count:星期几 。总数：key = user-count:total
     * @param type 需要计数的类型 用户 type=user-count
     * */
    public void addQuantity(String type){
        //今日新增
        //获取今天是星期几
        DayOfWeek dayOfWeek = LocalDateTime.now().getDayOfWeek();
        int value = dayOfWeek.getValue();
        String key = type+":"+value;
        Integer num = (Integer)redisUtils.get(key);
        if (num==null){
            //一天过期
            redisUtils.set(key,1,86400);
        }else {
            //数量加一
            redisUtils.set(key,1+num,86400);
        }

        //总数新增
        String totalKey = type+":"+"total";
        Integer totalNum = (Integer)redisUtils.get(totalKey);
        if (totalNum==null){
            redisUtils.set(totalKey,1);
        }else {
            //数量加一
            redisUtils.set(totalKey,1+totalNum);
        }

    }

    // content-main class
    public String contentMainClass(Boolean footer, Boolean tagsView) {
        if (!footer && !tagsView) {
            return "tagsview-footer-hide";
        } else if (!footer) {
            return "footer-hide";
        } else if (!tagsView) {
            return "tagsview-hide";
        }
        return StringUtils.EMPTY;
    }

    // 检查初始密码是否提醒修改
    public boolean initPasswordIsModify(Date pwdUpdateDate) {
        Integer initPasswordModify = Convert.toInt(configService.selectConfigByKey("sys.account.initPasswordModify"));
        return initPasswordModify != null && initPasswordModify == 1 && pwdUpdateDate == null;
    }

    // 检查密码是否过期
    public boolean passwordIsExpiration(Date pwdUpdateDate) {
        Integer passwordValidateDays = Convert.toInt(configService.selectConfigByKey("sys.account.passwordValidateDays"));
        if (passwordValidateDays != null && passwordValidateDays > 0) {
            if (StringUtils.isNull(pwdUpdateDate)) {
                // 如果从未修改过初始密码，直接提醒过期
                return true;
            }
            Date nowDate = DateUtils.getNowDate();
            return DateUtils.differentDaysByMillisecond(nowDate, pwdUpdateDate) > passwordValidateDays;
        }
        return false;
    }


    /**
     * 首页搜索
     */
    @GetMapping("/search/{key}")
    @ResponseBody
    public AjaxResult search(@PathVariable("key") String key){
        //将搜索放入redis缓存中
        String searchKey = "search-"+key;
        Object json = redisUtils.get(searchKey);
        if (json==null){
            List<Article> articles = articleService.selectArticleListByArticleTitle(key);
            json = JSON.toJSON(articles);
            redisUtils.set(searchKey,json,86400*3);
        }
        return  AjaxResult.success("成功",json);
    }

    /**新闻资讯*/
    @GetMapping("/news")
    public String newsView(Model model){
        // 取身份信息
        User user = getSysUser();
        PublicUser publicUser =null;
        if (user!=null){
            publicUser = user.getPublicUser(user);
        }
        model.addAttribute("selfUser",publicUser);

        return "system/news/news";
    }

    /**
     * 头条
     * */
    @GetMapping("/netEaseNews/index")
    @ResponseBody
    public AjaxResult getNetEaseNews(){
        String netEaseNews = showApiProvider.getNetEaseNews("T1348647853363");
        return AjaxResult.success("成功",netEaseNews);
    }


    /**
     * 精选新闻
     * */
    @GetMapping("/netEaseNews/foreign")
    @ResponseBody
    public AjaxResult getNetEaseNewsForeign(){
        String netEaseNews = showApiProvider.getNetEaseNews("T1467284926140");
        return AjaxResult.success("成功",netEaseNews);
    }




    /**
     * 获取热榜
     * */
    @GetMapping("/hotList")
    @ResponseBody
    public AjaxResult getHotList(){
        List<Article> hotList = null;
        //先从redis获取热榜文章
        String hotListKey = "article-hot-list";
        Object hotListObject = redisUtils.get(hotListKey);
        if (hotListObject==null){
            //从数据库中拿取详细数据
            hotList = getHotListByMySql();
            //一小时更新一次
            redisUtils.set(hotListKey,hotList,ruoYiConfig.getHotListUpdateTime());
        }else {
            hotList = (List<Article>)hotListObject;
        }

        return AjaxResult.success("成功",JSON.toJSON(hotList));
    }
    private List<Article> getHotListByMySql(){
        List<Article> articles = new ArrayList<>();
        //如果文章范围多，那么将文章，插入热榜。（插入逻辑，10天内，访问量达到50）
        String hotIdListKey = "article-hot-list-id";
        //热榜总数量
        Long total = redisUtils.countZset(hotIdListKey);
        //总页数
        long pageSize = total/10;
        if (total%10!=0){
            pageSize++;
        }
        int tag = 0;
        for (long i = 1; i <= pageSize; i++) {
            //只拿10条
            if (tag>=10){
                break;
            }
            Set<Object> hotList = redisUtils.rangeZset(hotIdListKey, (i-1)*10, i*10-1);
            for (Object o : hotList) {
                Integer articleId = (Integer) o;
                //排除3天以外的，并且将一个月以外的文章，从热榜移除
                Article article = articleService.selectArticleById(articleId.longValue());
                if (article!=null){
                    if (article.getArticleNewstime().getTime()+86400000*3>System.currentTimeMillis()){
                        tag++;
                        Double view = redisUtils.score(hotIdListKey, articleId);
                        article.setArticleViews(view.longValue());
                        articles.add(article);
                    }
                    //将一个月以外的文章，从热榜移除
                    if (article.getArticleNewstime().getTime()+86400000L*30L<System.currentTimeMillis()){
                        redisUtils.removeZset(hotIdListKey,articleId);
                    }
                } else {
                    //将不存在的文章删除
                    redisUtils.removeZset(hotIdListKey,articleId);
                }

            }
        }
        return articles;
    }

}
